#include "TokenManager.h"
#include "ScannerRule.h"

using namespace std;
using namespace stdext;

CTokenManager::CTokenManager():
m_strNoDebugString("N/A"),
m_terminateID(0),
m_nonterminateID(0)
{

    LOG("Initialize CTokenManager");

    NonterminateToken("S'",TOKEN_START_EXTENSION);
    NonterminateToken("S",TOKEN_START);

    //should be fine 
    NonterminateToken("number",TOKEN_NUMBER);
    NonterminateToken("word",TOKEN_WORD);
    NonterminateToken("empty",TOKEN_EMPTY);
    NonterminateToken("EOF",TOKEN_EOF);
    
}

CTokenManager::~CTokenManager()
{
    LOG("Destroy CTokenManager");
}

int CTokenManager::AddTokenDebugString( Token_Type Token, std::string strDebugString )
{
    hash_map<Token_Type, string>::iterator it = m_TokenDebugStringMap.find(Token);

    if (it == m_TokenDebugStringMap.end())
    {
        LOG("Production Parsing : ID mapping %s : %d",strDebugString.c_str(), Token);
        m_TokenDebugStringMap[Token] = strDebugString;
        return 0;
    }
    else
    {
        WFX_ASSERT(false);
    }

    

    return 0;
}

const std::string& CTokenManager::GetTokenDebugString( Token_Type Token )
{
    hash_map<Token_Type, string>::iterator it = m_TokenDebugStringMap.find(Token);

    if (it == m_TokenDebugStringMap.end())
    {
        //BUGBUG need throw?
        return m_strNoDebugString;
    }

    return m_TokenDebugStringMap[Token];
}

int CTokenManager::GenerateTerminateID()
{
    return TERMINATE_TOKEN | m_terminateID++;
}

int CTokenManager::GenerateNonTerminateID()
{
    return NONTERMINATE_TOKEN | m_nonterminateID++;
}

Token_Type CTokenManager::NonterminateToken( std::string str , Token_Type type)
{
    if (m_NonterminateToken.find(str) != m_NonterminateToken.end())
    {
        return m_NonterminateToken[str];
    }
    else
    {
        int ID = type ? type : GenerateNonTerminateID();
        m_NonterminateToken[str] = ID;

        AddTokenDebugString(ID,"<" + str + ">");

        return ID;
    }
}

Token_Type CTokenManager::Keyword( std::string str , Token_Type type)
{
    if (m_Keyword.find(str) != m_Keyword.end())
    {
        return m_Keyword[str];
    }
    else
    {
        int ID = type ? type : GenerateTerminateID();
        m_Keyword[str] = ID;

        AddTokenDebugString(ID,"[" + str + "]");

        if (m_pScannerRule)
        {
            m_pScannerRule->RegisterKeyWord(str.c_str(), ID);
        }

        return ID;
    }
}

Token_Type CTokenManager::SpecialToken( std::string str , Token_Type type)
{
    if (m_SpectialToken.find(str) != m_SpectialToken.end())
    {
        return m_SpectialToken[str];
    }
    else
    {
        int ID = type ? type : GenerateTerminateID();
        m_SpectialToken[str] = ID;

        AddTokenDebugString(ID,"\"" + str + "\"");

        if (m_pScannerRule)
        {
            m_pScannerRule->RegisterSpecialToken(str.c_str(), ID);
        }

        return ID;
    }
}

void CTokenManager::SetScannerRule( CScannerRulePtr pScannerRule )
{
    m_pScannerRule = pScannerRule;
}